home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_10_01
/
cmenu.exe
/
RMENU2.C
< prev
next >
Wrap
Text File
|
1991-11-12
|
8KB
|
368 lines
/************************************************************
* Program: RMENU Menu Interpreter
* Module: rmenu2.c
* Top-level menu processing
* Written by: Leor Zolman, 7/91
************************************************************/
#include "cmenu.h"
#include "rcmenu.h"
#include <ctype.h>
/************************************************************
* sub_menu():
* Run a local menu at the given nesting level
* Default command/menu path is supplied via "path".
************************************************************/
int sub_menu(mnum, path)
int mnum;
char *path;
{
MENU2 *M2p = LMenus[nestlev].Menus[mnum];
MENU *Mp = &M2p -> Menu;
char newpath[MAX_PATH];
int cur_item = 0;
int sel_val = 0;
int factor;
draw_menu(M2p, cur_item); /* display the menu */
strcpy(newpath, make_path(path, Mp -> path));
while (1)
{
switch (get_cmd(Mp -> nitems, cur_item, &sel_val))
{
case KEY_UP:
draw_item(M2p, cur_item, NORMAL, NO);
cur_item = cur_item ? cur_item - 1 :
Mp -> nitems - 1;
draw_item(M2p, cur_item, STANDOUT, YES);
break;
case KEY_DOWN:
draw_item(M2p, cur_item, NORMAL, NO);
cur_item = (cur_item == Mp -> nitems - 1) ? 0 :
cur_item + 1;
draw_item(M2p, cur_item, STANDOUT, YES);
break;
case KEY_RIGHT:
if (Mp -> columns == 1)
break;
draw_item(M2p, cur_item, NORMAL, NO);
factor = MAX_IROWS / Mp -> spacing;
if (cur_item + factor < Mp -> nitems)
cur_item += factor;
else
cur_item %= factor;
draw_item(M2p, cur_item, STANDOUT, YES);
break;
case KEY_LEFT:
if (Mp -> columns == 1)
break;
draw_item(M2p, cur_item, NORMAL, NO);
factor = MAX_IROWS / Mp -> spacing;
if (cur_item >= factor)
cur_item -= factor;
else
while (cur_item + factor < Mp -> nitems)
cur_item += factor;
draw_item(M2p, cur_item, STANDOUT, YES);
break;
case KEY_RUN:
if (M2p -> Items[cur_item] -> acttyp == ACT_EXIT)
return OK;
if (do_item(M2p, cur_item, newpath) == EXITALL)
return EXITALL;
switch(M2p -> Items[cur_item] -> nextcode)
{
case NXT_FIRST:
cur_item = 0;
break;
case NXT_LAST:
cur_item = M2p -> Menu.nitems - 1;
break;
case NXT_NEXT:
if (cur_item < M2p -> Menu.nitems - 1)
cur_item++;
break;
case NXT_DIRECT:
cur_item = M2p -> Items[cur_item] -> nextitem;
break;
}
draw_menu(M2p, cur_item); /* redisplay menu */
break;
case K_DIRECT:
if ((sel_val - 1) != cur_item)
{
draw_item(M2p, cur_item, NORMAL, NO);
cur_item = sel_val - 1;
draw_item(M2p, cur_item, STANDOUT, YES);
}
break;
case K_SHELL:
if (M2p -> Menu.escape == YES ||
(M2p -> Menu.escape == DEFAULT && DEF_ESCAPE == YES))
{
#if SHELL_PROMPT
if (put_msg(0, SH_PROMPT_STR) == ESC)
break;
#else
move(ERR_ROW, 0);
standout();
addstr("Invoking shell. . .");
standend();
#endif
pre_shell(); /* set up for shell call */
system(SHELL_ESC); /* run a shell */
post_shell(); /* restore everything */
draw_menu(M2p, cur_item);
}
else
put_msg(1, "Sorry, shell escapes are disabled.");
break;
case K_EXIT:
return OK;
case K_EXITALL:
return EXITALL;
case K_VERSION:
put_msg(0, " RMENU Menu Interpreter v%s ",
VERSION);
break;
case K_UNKNOWN:
beep();
}
refresh();
}
}
/************************************************************
* draw_menu():
* Display the entire menu, including all prompts,
* and titles and help text (if any) for current item
* on the screen.
************************************************************/
Void draw_menu(M2p, curr)
MENU2 *M2p;
int curr;
{
MENU *Mp = &M2p -> Menu;
int title_len = strlen(Mp -> title);
int i, j;
clear();
move(TITLE_ROW, (SCREEN_COLS - title_len)/2);
addstr(Mp -> title); /* Put up menu title */
for (i = 0; i < Mp -> nitems; i++)
if (i == curr)
draw_item(M2p, i, STANDOUT, YES);
else
draw_item(M2p, i, NORMAL, NO);
move(PROMPT_ROW, 0);
addstr(MENU_OPTS);
if (Mp -> escape == YES ||
(Mp -> escape == DEFAULT && DEF_ESCAPE == YES))
addstr(MENU_SHELL);
addstr(MENU_PROMPT);
getyx(stdscr, echoy, echox); /* save coords of item # echo area */
refresh(); /* display the window */
}
/************************************************************
* draw_item():
* Display a single item (the current item) of the
* specified menu, using the specified video mode.
* Display assiciated help text only if "dohelp"
* is TRUE.
************************************************************/
Void draw_item(M2p, item, vid_mode, dohelp)
MENU2 *M2p;
int item, vid_mode, dohelp;
{
ITEM *Ip = M2p -> Items[item];
COORDS *Cp = &M2p -> coords[item];
int j;
move (Cp->ypos, Cp->xpos);
printw("%2d.", item + 1);
if (vid_mode == STANDOUT)
standout();
printw(" %s", Ip -> text);
for (j = 0; j < Cp -> spaces_needed; j++)
addch(' ');
if (vid_mode == STANDOUT)
standend();
if (dohelp == YES)
{
move(HELP_ROW0, HELP_COL0);
if (*Ip -> help)
{
addstr(" HELP: "); /* display help text */
standout();
move (HELP_ROW, (80 - strlen(Ip -> help))/2);
addstr(Ip -> help);
standend();
}
else
{
addstr(" "); /* clear help text area */
move(HELP_ROW, 0);
}
clrtoeol();
}
}
/************************************************************
* get_cmd()
* Get a command from the user.
* Arrow keys or space returns the appropriate K_ code.
* Pressing Enter returns the K_RUN code.
* Pressing ! returns the K_SHELL code.
* Entering a direct number returns K_DIRECT,
* and the sel_val is set (indirectly) to selection number
* (1-based).
************************************************************/
int get_cmd(nitems, curr, sel_val)
int nitems;
int curr;
int *sel_val;
{
int ch;
int newval;
int savy, savx;
static int digits = FALSE; /* true if digits being entered */
move(echoy, echox); /* move to prompt location */
printw("%d", curr + 1);
getyx(stdscr, savy, savx);
clrtoeol();
move(savy, savx);
refresh();
while (1)
{
ch = getch();
if (!isdigit(ch))
digits = FALSE;
switch (ch)
{
case KEY_UP:
case '\b': /* WYSE 60s send this for left arrow */
clrtoeol();
return KEY_UP;
case ' ':
case KEY_DOWN:
#if UNIX || XENIX
case '\n': /* WYSE 60s send this for down arrow */
#endif
clrtoeol();
return KEY_DOWN;
case KEY_RIGHT:
return KEY_RIGHT;
case KEY_LEFT:
return KEY_LEFT;
case KEY_RUN:
return KEY_RUN;
case 'e':
case 'E':
return K_EXIT;
case 'x':
case 'X':
return K_EXITALL;
case 'v':
case 'V':
return K_VERSION;
case '!':
return K_SHELL;
case ESC: /* clear digits area */
digits = FALSE;
move(echoy, echox);
clrtoeol();
refresh();
break;
default: /* handle digits */
if (!isdigit(ch))
return K_UNKNOWN;
if (digits &&
(newval = *sel_val * 10 + (ch - '0')) <= nitems
&& newval > 0)
{
addch(ch);
refresh();
*sel_val = newval;
return K_DIRECT;
}
else if ( (newval = ch - '0') && newval <= nitems)
{
digits = TRUE;
move(echoy, echox);
addch(ch);
clrtoeol();
refresh();
*sel_val = newval;
return K_DIRECT;
}
else
{
digits = FALSE;
beep();
}
}
}
}